package com.fdb.efp.console.executor;

import com.fdb.basic.framework.core.constant.FlowExceptionType;
import com.fdb.basic.framework.core.exception.FlowException;
import com.fdb.basic.framework.core.exception.TerminateException;
import com.fdb.efp.console.common.constance.FlowConstance;
import com.fdb.efp.console.common.service.Executor;
import com.fdb.efp.console.common.vo.EngineVO;
import com.fdb.efp.console.service.facade.InstFlowParamService;
import com.fdb.efp.console.service.facade.InstFlowTaskService;
import com.fdb.efp.console.service.vo.InstFlowTaskVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * 
 * 页面任务提交执行器
 * 
 * @author Cytus_
 * @since 2018年5月29日 下午4:50:24
 * @version 1.0
 *
 */
@Service("pageTaskSubmitExecutor")
public class PageTaskSubmitExecutor extends NodeExecutor {

	private static Logger logger = LoggerFactory.getLogger(PageTaskSubmitExecutor.class);
	
	@Autowired
	@Qualifier("taskExecutorFlow")
	private Executor taskExecutor;
	
	@Autowired
	@Qualifier("instFlowTaskService")
	private InstFlowTaskService instFlowTaskService;
	
	@Autowired
	@Qualifier("instFlowParamService")
	private InstFlowParamService instFlowParamService;
	
	public EngineVO execute(EngineVO evo) throws FlowException {
		
		evo.setNodeExecuteStatus(FlowConstance.NODE_STATUS_RUNNING);
		updateFLowProcessStatus(evo.getNodeInstanceId(), evo.getNodeExecuteStatus());
		
		/*
		 * 寻找当前节点下需要等待执行的任务
		 * 1：节点下任务未初始化，先出使话任务列表，在寻找节点下首先要执行的任务
		 * 2：节点下任务已经初始化话，寻找任务状态为暂停的任务
		 */
		InstFlowTaskVO task = findCurrExeTask(evo.getNodeInstanceId(), evo.getTaskId());
		if (Objects.isNull(task)) {
			throw new FlowException("当前节点实例:"+ evo.getNodeInstanceId() +", 业务节点："+ evo.getNodeId() +"未找到需要执行的节点下任务");
		}
		
		logger.info("当前节点实例:"+ evo.getNodeInstanceId() +", 待执行任务为："+ task.getTaskId());
		
		try {
			
			//如果寻找的当前任务，将序列化存储到数据库中的pluginVo对象反序列化出来
			try {
				evo = getPluginVoInfos(evo);
			} catch (Exception e) {
				logger.error("当前节点实例:"+ evo.getNodeInstanceId() +", 业务节点："+ evo.getNodeId() +", 上下文数据信息提取出现异常!", e);
				throw new FlowException(e.getMessage(), e);
			}
			
			evo.setTaskExecuteStatus(task.getTaskState());
			evo.setTaskId(task.getTaskId());
			evo.setPreTaskId(task.getPreviousTaskId());
			logger.info("当前节点实例:"+ evo.getNodeInstanceId() +", 执行任务："+ evo.getTaskId() +"开始......");
			taskExecutor.execute(evo);
			logger.info("当前节点实例:"+ evo.getNodeInstanceId() +", 执行任务："+ evo.getTaskId() +"结束, 任务状态为:"+ evo.getTaskExecuteStatus());
			
			if (FlowConstance.TASK_STATUS_END.equals(evo.getTaskExecuteStatus())) {
				savePluginVoInfos(evo);
			}
			
			evo.setNodeExecuteStatus(FlowConstance.NODE_STATUS_PAUSE);
		} catch(TerminateException e) {
			logger.error("当前节点ID:"+ evo.getNodeId() +", 实例化流水:"+ evo.getNodeInstanceId() +"执行出现终止异常!", e);
			if (FlowExceptionType.NODE.equals(e.getFlowExceptionType())) {
				evo.setTaskExecuteStatus(FlowConstance.NODE_STATUS_END);
			} 
			throw e;
		} catch (Exception e) {
			logger.error("当前节点ID:"+ evo.getNodeId() +", 实例化流水:"+ evo.getNodeInstanceId() +"执行异常!", e);
			evo.setNodeExecuteStatus(FlowConstance.NODE_STATUS_EXCEPTION);
		} finally {
			updateFLowProcessStatus(evo.getNodeInstanceId(), evo.getNodeExecuteStatus());
		}
		return evo;
	}
	
	/**
	 * 根据节点实例号和任务编号查询
	 * @param instNodeId
	 * @param taskId
	 * @return
	 */
	private InstFlowTaskVO findCurrExeTask(String instNodeId, String taskId) {
		InstFlowTaskVO queryVo = new InstFlowTaskVO();
		queryVo.setInstNodeId(instNodeId);
		queryVo.setTaskId(taskId);
		return instFlowTaskService.queryTaskByNodeTaskId(queryVo);
	}

}
